<template>
    <div>
    <div class="button-container">
      <!-- 按钮触发文件选择 -->
      <button id="clickBtn" @click="loadModel">加载模型</button>
      <button id="clickBtn" @click="exportModel">保存模型</button>
      <button id="clickBtn" @click="removeModel">移除模型</button>
      
      <button id="clickBtn" @click="loadBatchModel">批量加载显示模型</button>
      <!-- <button id="clickBtn" @click="createBatchModel">批量保存模型</button> -->
  
    </div>

  </div>
</template>

<script setup lang='ts'>
import { ref } from 'vue';

import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 导入GLTFExporter
import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';
// 导入GLTFLoader
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
// 导入DracoLoader
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";

// 洪湖建模函数入口
import { 
  Main,CreateModelFromData,CreateGeometryFromURL
} from '../scripts/LoadLakeMesh';
import {
  GetFileURL
} from '../scripts/getContentFromUrl.ts';

// -------------------------Threejs部分内容-----------------
// 初始化场景
const scene = new THREE.Scene();

// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100000);


// 设置相机位置
camera.position.set(5000,50000,50000);
// 设置相机朝向点
camera.lookAt(0, 0, 0);


// 创建渲染器
const renderer = new THREE.WebGLRenderer({
  //设置抗锯齿
  antialias:true,
});
// 设置渲染器大小为窗口大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 添加到界面中
document.body.appendChild(renderer.domElement);


// 添加轨道控制器(控制的是相机)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置带阻尼的惯性
controls.enableDamping = true;
// 设置阻尼系数，系数越小惯性越大
controls.dampingFactor = 0.05;

// 鼠标控制
controls.mouseButtons = {
  //左键平移
  LEFT: THREE.MOUSE.PAN,
  //滚轮滑动
  MIDDLE: THREE.MOUSE.DOLLY,
  //右键旋转
  RIGHT: THREE.MOUSE.ROTATE,
};

// AxesHelper：辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);

//----------------------
// 添加具体的代码
console.log("exportModel.vue is running.");

// 测试场景
// Main(scene);

let mesh:THREE.Mesh = null;


// 循环渲染

function render() {
  controls.update();

  // 每帧执行此函数
  requestAnimationFrame(render);

  // 渲染
  renderer.render(scene, camera);

}

render();

// 监听窗口变化更新renderer
window.addEventListener("resize", () => {
  // console.log("resize");
  // 重置渲染器宽高比
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 重置相机宽高比
  camera.aspect = window.innerWidth / window.innerHeight;
  // 更新相机投影矩阵
  camera.updateProjectionMatrix();
});


// -------------------------------
// 其他界面交互相关函数

// 点击批量加载按钮
async function loadBatchModel(){
   // 创建材质和网格
   const material = new THREE.MeshBasicMaterial({
    // color: 0xffffff,
    vertexColors: true, // 启用顶点颜色
    transparent: true,// 使用顶点颜色中的alpha值
    // wireframe: true,   // 根据需求选择是否启用线框模式
    side: THREE.DoubleSide,
  });

  // TODO：动态切换已经加载的模型
  const pltFileURL = "http://127.0.0.1:8080/TEC_WQR/TEC_WQRSUM_180.000.PLT";//用来构建洪湖网格模型的索引
  
  const waterWQRUrl = "http://127.0.0.1:8081/TIME_WQR/";//批量构建洪湖三维模型的DAT文件夹
  // 初始化文件加载
  let fileUrls = await getAllURLFromDir(waterWQRUrl);
  
  for (let index = 0; index < fileUrls.length; index++) {
    const fileURL = fileUrls[index];
    let fileName = getFileNameWithoutExt(fileURL);
    
    let geometry = await CreateGeometryFromURL(pltFileURL,fileURL);
    let mesh = new THREE.Mesh(geometry, material);

    glbMeshes[fileName] = mesh;
  }

  console.log("文件夹中模型构建结果：",glbMeshes);


  // 将已经加载的模型进行动态切换显示
  let keys = Object.keys(glbMeshes); // 获取所有模型字典中的键
  console.log("keys:",keys);

  let index = 0;
  function processNextMesh() {
    if (index < keys.length) {
        let key = keys[index];
        console.log("Mesh Name:", key);

        if(mesh){
          scene.remove(mesh);
          mesh = null;
        }else{
          mesh = glbMeshes[key];
          scene.add(mesh);
          console.log("next mesh change.");
        }

        index++;
        setTimeout(processNextMesh, 2000); // 每隔2秒递归调用
    }
  }

  processNextMesh(); // 开始处理第一个网格
  console.log("All Meshes have showed.");

}


// INFO:点击加载模型按钮触发
async function loadModel(){
  const fiveLevelGeometry = await CreateModelFromData();
  console.log("fiveLevelGeometry:",fiveLevelGeometry);


  // 创建材质和网格
  const material = new THREE.MeshBasicMaterial({
      // color: 0xffffff,
      vertexColors: true, // 启用顶点颜色
      transparent: true,// 使用顶点颜色中的alpha值
      // wireframe: true,   // 根据需求选择是否启用线框模式
      side: THREE.DoubleSide,
  });

  
  mesh = new THREE.Mesh(fiveLevelGeometry, material);
  
  scene.add(mesh);

}


function removeModel(){
  // if(mesh)
  //   scene.remove(mesh);
  // else
  //   console.log("no model to remove");

  removeAllModelInScene(scene);
}

// 一次性把链接中所有的模型全部创建并保存
let glbMeshes = {};

// INFO:点击批量保存模型按钮触发
async function createBatchModel(){
  // 创建材质和网格
  const material = new THREE.MeshBasicMaterial({
    // color: 0xffffff,
    vertexColors: true, // 启用顶点颜色
    transparent: true,// 使用顶点颜色中的alpha值
    // wireframe: true,   // 根据需求选择是否启用线框模式
    side: THREE.DoubleSide,
  });


  // TODO：
  const pltFileURL = "http://127.0.0.1:8080/TEC_WQR/TEC_WQRSUM_180.000.PLT";//用来构建洪湖网格模型的索引
  
  // 替换为自己的文件夹地址
  const waterWQRUrl = "http://127.0.0.1:8081/TIME_WQR/";//构建洪湖三维模型
  // 初始化文件加载
  let fileUrls = await getAllURLFromDir(waterWQRUrl);
  
  for (let index = 0; index < fileUrls.length; index++) {
    const fileURL = fileUrls[index];
    let fileName = getFileNameWithoutExt(fileURL);
    
    let geometry = await CreateGeometryFromURL(pltFileURL,fileURL);
    let mesh = new THREE.Mesh(geometry, material);

    glbMeshes[fileName] = mesh;
  }

  console.log("文件夹中模型构建结果：",glbMeshes);
  
// for (let key in glbMeshes) {
//     console.log("Mesh Name:",key);
//     exportGLTF(glbMeshes[key],{
//       filename:key,
//     });
    
// }

let keys = Object.keys(glbMeshes); // 获取所有模型字典中的键
let index = 0;

function processNextMesh() {
  if (index < keys.length) {
      let key = keys[index];
      // console.log("Mesh Name:", key);

      // if(mesh){
      //   scene.remove(mesh);
      //   mesh = null;
      // }else{
      //   mesh = glbMeshes[key];
      //   scene.add(mesh);
      //   console.log("next mesh change.");
      // }

      // 批量弹出下载
      exportGLTF(glbMeshes[key], {
          filename: key,
      });

      index++;
      setTimeout(processNextMesh, 2000); // 每隔2秒递归调用
  }
}

processNextMesh(); // 开始处理第一个网格

console.log("All Meshes Exported.");




}

function getFileNameWithoutExt(fullPath:string) {
  // 获取文件名带后缀
  let fileNameWithExt = fullPath.substring(fullPath.lastIndexOf('/') + 1);
  // 去掉后缀
  let fileNameWithoutExt = fileNameWithExt.split('.').slice(0, -1).join('.');
  // 如果文件名中包含多个点，则上述方法会返回除去最后一个点之前的部分，
  // 若想简单处理只有单个后缀名的情况，可以直接使用 fileNameWithExt.split('.')[0]
  return fileNameWithoutExt;
}

async function getAllURLFromDir(baseUrl:string) {
  let fileUrls:string[];
  fileUrls = await GetFileURL(baseUrl,'.DAT');
  console.log("fileUrls:", fileUrls);

  if(fileUrls.length > 0){
    return fileUrls;
  }else{
    console.error("Failed to get dat file from url.");
    return;
  }

}
//----------------------批量保存文件结束-----------------------

const removeAllModelInScene = (scene:THREE.scene) =>{
  scene.traverse((object) => {
    if (object instanceof THREE.Mesh) {
      scene.remove(object);
    }
  });
}


// INFO:保存模型按钮触发
function exportModel(fileName:string = ''){
  // console.log("You have clicked the button.");

  let outputFileName : string;
  if(fileName == ''){
    outputFileName = fileName;
  }
  else{
    let tmpFileName = getCurrentDateTimeFormatted();
    console.log("tmpFileName:",tmpFileName);
    outputFileName = tmpFileName;

  }

  exportGLTF(mesh,{
    filename:outputFileName,
  });
}


function getCurrentDateTimeFormatted() {
    // 获取当前的日期和时间
    const now = new Date();
 
    // 提取年、月、日、时、分、秒
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始，需要加1，并补零
    const day = String(now.getDate()).padStart(2, '0'); // 补零
    const hours = String(now.getHours()).padStart(2, '0'); // 补零
    const minutes = String(now.getMinutes()).padStart(2, '0'); // 补零
    const seconds = String(now.getSeconds()).padStart(2, '0'); // 补零
 
    // 拼接成所需的格式
    const formattedDateTime = `${year}-${month}-${day}-${hours}-${minutes}-${seconds}`;
 
    return formattedDateTime;
}

// 导出GLTF模型
function exportGLTF(mesh:THREE.Mesh,option){
  if(!mesh){
    console.log("Mesh has not been created.");
    return;
  }
  console.log("mesh.geometry:",mesh.geometry);

  const exporter = new GLTFExporter();
  const options = {
    trs: option.trs == null ? false : option.trs, //导出位置、旋转和缩放，而不是每个节点的矩阵 默认是false
    onlyVisible: option.onlyVisible == null ? true : option.onlyVisible, //只导出可见的对象 默认是true
    truncateDrawRange: option.truncateDrawRange == null ? true : option.truncateDrawRange,
    binary: true,//option.binary == null ? false : option.binary, //binary==true 导出glb | binary==false 导出gltf
    forceindices: option.forceindices == null ? false : option.forceindices, //为非索引几何图形生成索引并导出它们 默认false
    maxTextureSize: 4096, //限制图像的最大尺寸（宽度、高度）为给定值。默认是无限
  };

  // Parse the input and generate the glTF output
  exporter.parse(
    mesh,
    // called when the gltf has been generated
    (gltf)=>{
        console.log("gltf:",gltf);

      // 将模型保存为glb
      save(new Blob([gltf], { type: 'model/gltf-binary' }), `${option.filename}.glb`);
    },
    // called when there is an error in the generation
    (error)=>{
      console.log( 'An error happened' );
    }, options);


  function save(blob:Blob, filename:string) {
    const link = document.createElement('a');
    link.style.display = 'none';
    document.body.appendChild(link); // Firefox workaround, see #6594
    // console.log(document.body);//无法看到document中的link

    link.href = URL.createObjectURL(blob);
    link.download = filename;
    link.click();
    // console.log("link:",link);
    document.body.removeChild(link);
    // console.log(document.body);//这句话执行时是查询了最终状态的document内容，故而a不显示
  }

}




</script>


<style scoped>
/* 铺满整个网页 */
*{
  margin:0;
  padding: 0;
}
/* 设置画布canvas铺满，并位于左上角 */
canvas{
  width:100vw;
  height:100vh;
  position:fixed;
  left:0;
  top:0;
}

.button-container {
  position: absolute;
  display: grid;
  grid-template-columns: 1fr; 
  gap: 10px; 
  z-index: 99;
}

</style>